/**
 * 名称：创建viewer实体
 * 说明：创建viewer并配置Cesium界面控件的显隐
 * 参数：
 * 状态：已完成
 * 负责人：/
 */
const createViewer = () => {
  // Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyODVjNjIyZC1mNzM0LTRhYzYtYTgwMi1jYWJkYzI5ZWQxZWMiLCJpZCI6MTE4NzMwLCJpYXQiOjE2NzE0MzIyMzl9.QxpI6eIOZqMRiqIxuAi2DD22_68pG9RQePfgJjHZpJ4'
  viewer = new Cesium.Viewer('cesiumContainer', {
    homeButton: false,
    sceneModePicker: false, //是否显示投影方式控件
    baseLayerPicker: true,  //是否显示图层选择控件
    navigationHelpButton: false, //是否显示帮助信息控件
    geocoder: false, //是否显示地名查找控件
    animation: false, //是否显示动画控件
    timeline: false, //是否显示时间线控件
    fullscreenButton: false,
    vrButton: false,
    shadows: false, //影子
    infoBox: false, //是否显示点击要素之后显示的信息
    selectionIndicator: false// 关闭点击球体显示绿色框关闭
  })
}

/**
 * 名称：地图操作
 * 说明：加载GIS地图及切换
 * 参数：
 * 状态：已完成
 * 负责人：/
 */
const createGIS = (number) => {
  viewer.baseLayerPicker.viewModel.selectedImagery = viewer.baseLayerPicker.viewModel.imageryProviderViewModels[3]
}

/**
 * 名称：获取项目json地址
 * 说明：获取项目编号
 * 参数：
 * 状态：展示不做
 * 负责人：/
 */
const gitProjectNo = () => {

}

/**
 * @description 读取JSON文件，拿到构件的地址
 * @param url 地址
 */
const getJsonData = (url) => {
  //   获取json 拿到地址数据
  $.get(url, function(data) {
    let item = JSON.parse(JSON.stringify(data.scenes[0]))
    // 深拷貝
    all3dTilesLayerData.push(JSON.parse(JSON.stringify(item)))
    // 平铺
    for(let i = 0; i < data.scenes.length; i++) {
      tileObject(data.scenes[i].children, all3dTilesPositionObj)
    }
  })
}
/**
 * @description 清空数据
 */
const clearAllData = () => {
  all3dTilesLayerData = []
  all3dTilesPositionObj = {}
  all3dTilesFieldNameArr = null
  all3dTilesObjArr = {}
  recordTilesetData = new Map()
}
/**
 * 名称：加载3Dtile模型
 * 说明：通过id或者json数据添加3Dtile模型数据
 * 参数：tileArr:[{type:id/json,tileData:id1,/jsonPath1,layerName:建组}]
 * type：3Dtile类型，使用字符串标注”id“或者"json"
 * tileData：3Dtile数据id或者json地址集合信息信息，以防出现多个3Dtile的加载
 * layerName：图层名称
 * 状态：正在开发
 * 负责人：/
 */
// 图层列表
let layerListData = []
const add3Dtile = async(tileArr) => {
  let layerData = null
  clearAllData()
  for(const index in tileArr) {
    // 读取JSON文件存起来
    await getJsonData(tileArr[index].tileData.replace('tileset', 'scenetree'))
    if(tileArr[index].subset.length > 0) {
      let multistage = new Map()
      let subset = new Map()
      for(const indexKey in tileArr[index].subset) {
        subset.set(tileArr[index].subset[indexKey].layerName, tileArr[index].layerNam + '-' + tileArr[index].subset[indexKey].layerName)
        installDataTypeJudgment(tileArr[index].subset[indexKey])
      }
      multistage.set(tileArr[index].layerName, subset)
      layerListData.push(multistage)
    } else {
      installDataTypeJudgment(tileArr[index])
      let singleStage = new Map()
      let parentData = new Map()
      parentData.set(tileArr[index].layerName, tileArr[index].layerName)
      singleStage.set(tileArr[index].layerName, parentData)
      layerListData.push(singleStage)
    }
  }
  console.log('查看组织的图层数据all3dTilesLayerData：', all3dTilesLayerData)
  console.log('查看组织的图层数据：', layerListData)
}

/**
 * 名称：数据类型判断
 * 说明：通过json文件中3dtile的Tyoe类型进行判断并调用方法
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
function installDataTypeJudgment(layerData) {
  if(layerData !== null) {
    switch(layerData.type) {
      case 'id':
        return createThroughID3Dtile(layerData.tileData, layerData.layerName)
      case 'json':
        return createThroughJSON3Dtile(layerData.tileData, layerData.layerName)
    }
  }
}

/**
 * 名称：通过id加载3Dtile模型
 * 说明：根据传入的id信息来进行3Dtile模型的添加
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
const createThroughID3Dtile = async(id) => {
  try {
    tileset = await Cesium.Cesium3DTileset.fromIonAssetId(id)
    const translation = new Cesium.Cartesian3(
      -1.398521324920626,
      0.7823052871729486,
      0.7015244410592609
    )
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
    tileset.maximumScreenSpaceError = 8.0
    viewer.scene.pickTranslucentDepth = true
    viewer.scene.light.intensity = 7.0
    viewer.scene.primitives.add(tileset)
    // 3D Tiles加载完成后执行的代码
    tileset.readyPromise.then(function() {
      console.log('模型加载完成')
    })
    // 存储所有的3Dtile信息，方面后期剖切使用
    globalTilesetArr.push(tileset)
    globalTranslationArr.push(translation)
  } catch(error) {
    console.log(`Error loading tileset: ${error}`)
  }
}

/**
 * 名称：通过Json加载3Dtile模型
 * 说明：根据传入的Json信息来进行3Dtile模型的添加
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
const createThroughJSON3Dtile = (tilePath, layerName) => {
  //加载倾斜示范数据
  let translation = new Cesium.Cesium3DTileset({
    url: tilePath,
    //控制切片视角显示的数量，可调整性能
    maximumScreenSpaceError: 2,
    maximumNumberOfLoadedTiles: 100000
  })
  //控制模型的位置
  translation.readyPromise.then(function(translation) {
    //添加到场景
    tileset = viewer.scene.primitives.add(translation)
    recordTilesetData.set(layerName, { tileset: tileset, translation: translation, status: true, transparency: 1 })
    // 定位
    viewer.zoomTo(translation, new Cesium.HeadingPitchRange(0.0, -0.5, translation.boundingSphere.radius * 2.0))
    // 组装构件数据，方便以后查询
    tileset.tileLoad.addEventListener(function(tile) {
      let content = tile.content
      let featuresLength = content.featuresLength
      // console.log(featuresLength)
      if(content.featuresLength > 0) {
        for(let i = 0; i < content.featuresLength; i++) {
          //用来存储每个构件的属性
          let arr = {}
          // 每个构件
          let feature = content.getFeature(i)
          // 得到构件的所有属性名
          const propertyIds = feature.getPropertyIds()
          // 保存一次构件属性名
          all3dTilesFieldNameArr ||= propertyIds
          const length = propertyIds.length
          // 根据数组长度遍历
          for(let j = 0; j < length; ++j) {
            const propertyId = propertyIds[j]
            arr[propertyId] = feature.getProperty(propertyId)
          }
          // 保存构件对象
          all3dTilesObjArr[arr['id']] = feature
          all3dTilesArr.push(arr)
        }
        // console.log('all3dTilesArr', all3dTilesArr)
        // console.log('all3dTilesObjArr', all3dTilesObjArr)
        // console.log('all3dTilesObjArr..length', Object.keys(all3dTilesObjArr).length)

        // 下载为json文件
        // downloadFile(new File([JSON.stringify(fileCtx, null, 2)], 'hello-world.json', { type: 'application/json' }))
      }

    })
    // 存储所有的3Dtile信息，方面后期剖切使用
    globalTilesetArr.push(tileset)
    globalTranslationArr.push(translation)
  }).catch(function(error) {
    console.log(error)
  })

}

/**
 * @description 平铺数组为对象
 * @param arr ○数组
 * @param obj 存储对象
 */
const tileObject = (arr, obj) => {
  if(arr instanceof Array && arr?.length) {
    arr.map((item, index) => {
      obj[item.id] = item
      tileObject(item.children, obj)
    })
  }

}

/**
 * 下载文件
 * 描述：下载文件
 * 参数：
 * file：file对象
 * name: 取一个文件名称
 * 返回值：无
 * 参考网址：无
 */
function downloadFile(file, name) {
  console.log('-----file-----', file)
  name = file.name || ''
  name = decodeURI(name)
  // name = name.split('=')[1]
  const type = file.type || 'application/octet-stream'
  const blobFile = new Blob([file], { type: type })
  const href = URL.createObjectURL(blobFile)
  const a = document.createElement('a') // 创建一个a节点插入的document
  const event = new MouseEvent('click') // 模拟鼠标click点击事件
  a.download = name // 设置a节点的download属性值
  a.href = href // 将图片的src赋值给a节点的href
  a.dispatchEvent(event) // 触发鼠标点击事件
}

/**
 * 名称：模型json数据加载
 * 说明：加载关于3Dtile的模型数据信息，将其整理到一个Map中，为后面的模型加载做准备
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
const loading3DtileJsonData = () => {
  $.getJSON('Source/mian/SDK/json/3Dtile.json', function(data) {
    // let tileData = data['3DtileData']['jidian']
    let tileData = data['3DtileData']['foshantest-jiu']
    // let tileData = data['3DtileData']['foshantest-xin']

    console.log('查看模型信息：', tileData)
    // 数据组装
    add3Dtile(tileData)
  })
}

/**
 * 名称：创建点击事件
 * 说明：讲点击事件赋值给全局变量进行存储
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
const createHandler = () => {
  handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
}

/**
 * 名称：预加载绘制线条
 * 说明：因为测量线段第一次创建出现会很慢，所以为了避免就直接先提前做个创建，来解决创建慢的问题
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
function preloadPolyline() {
  let positionArr = [
    { x: -2177321.659906258, y: 4388014.944454873, z: 4071060.0067683873 }
    , { x: -2177362.996706154, y: 4387995.0256338995, z: 4071059.372272701 }]
  drawLinesArr(positionArr, 0)

}

/**
 * 名称：初始化
 * 说明：初始化方法
 * 参数：
 * 状态：正在开发
 * 负责人：/
 */
const init = () => {
  createViewer()
  createGIS()
  loading3DtileJsonData()
  createHandler()
  preloadPolyline()
}
init()
